﻿using System;
using Unity.Collections;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 滚动模式
/// </summary>
public enum enSFUI_ScrollRect_ScrollMode
{
    /// <summary>
    /// 水平
    /// </summary>
    Horizontal = 0,
    /// <summary>
    /// 垂直
    /// </summary>
    Vertical = 1,
}

/// <summary>
/// 布局类型
/// </summary>
public enum enSFUI_ScrollRect_LayoutGroupType
{
    /// <summary>
    /// 水平或垂直布局
    /// </summary>
    HorizontalOrVerticalLayoutGroup = 0,
    /// <summary>
    /// Grid布局
    /// </summary>
    GridLayoutGroup = 1,
}

/// <summary>
/// SFUI_ScrollRect组件[Setting]
/// </summary>
public partial class SFUI_ScrollRect
{
    /// <summary>
    /// 布局类型
    /// </summary>
    [SerializeField]
    enSFUI_ScrollRect_LayoutGroupType mLayoutGroupType = enSFUI_ScrollRect_LayoutGroupType.HorizontalOrVerticalLayoutGroup;
    /// <summary>
    /// 布局类型
    /// </summary>
    public enSFUI_ScrollRect_LayoutGroupType layoutGroupType { get { return mLayoutGroupType; } }
    /// <summary>
    /// 滚动模式
    /// </summary>
    [SerializeField]
    enSFUI_ScrollRect_ScrollMode mScrollMode = enSFUI_ScrollRect_ScrollMode.Vertical;
    /// <summary>
    /// 滚动模式
    /// </summary>
    public enSFUI_ScrollRect_ScrollMode scrollMode { get { return mScrollMode; } }
    /// <summary>
    /// 是否可滚动
    /// </summary>
    [SerializeField]
    bool mCanScroll = true;
    /// <summary>
    /// 是否可滚动
    /// </summary>
    public bool canScroll { get { return mCanScroll; } set { mCanScroll = value; } }
    /// <summary>
    /// 是否无限循环
    /// </summary>
    [SerializeField]
    bool mIsInfiniteLoop = false;
    /// <summary>
    /// 是否循环
    /// </summary>
    public bool isLoop { get { return mIsInfiniteLoop; } }
    /// <summary>
    /// 获得Item模板
    /// </summary>
    Func<int, GameObject> mFuncGetItemTemplete = null;
    /// <summary>
    /// 更新Item
    /// </summary>
    Action<SFUI_ScrollRectItem> mActionUpdateItem = null;
    /// <summary>
    /// 获得当前数据的数量
    /// </summary>
    Func<int> mFuncGetItemCount = null;    
    /// <summary>
    /// 布局
    /// </summary>
    LayoutGroup mLayoutGroup = null;
    /// <summary>
    /// 绑定模拟脚本
    /// </summary>
    public Func<SFUI_ScrollRectItem, ISimulateBehaviour> mFuncBindSimulateBehaviour { get; private set; }

    #region OnCheckLayoutGroup 检测布局
    /// <summary>
    /// 检测布局
    /// </summary>
    /// <param name="_lg">布局控件</param>
    void OnCheckLayoutGroup(LayoutGroup _lg)
    {
        switch (mLayoutGroupType)
        {
            case enSFUI_ScrollRect_LayoutGroupType.HorizontalOrVerticalLayoutGroup:
                HorizontalOrVerticalLayoutGroup hov = null;
                switch (mScrollMode)
                {
                    case enSFUI_ScrollRect_ScrollMode.Horizontal:
                        if (_lg is HorizontalLayoutGroup)
                        {
                            hov = _lg as HorizontalOrVerticalLayoutGroup;
                        }
                        else
                        {
                            _lg.ImmediateDestory();
                            hov = content.gameObject.AddComponent<HorizontalLayoutGroup>();                            
                        }
                        break;
                    case enSFUI_ScrollRect_ScrollMode.Vertical:
                        if (_lg is VerticalLayoutGroup)
                        {
                            hov = _lg as HorizontalOrVerticalLayoutGroup;
                        }
                        else
                        {
                            _lg.ImmediateDestory();
                            hov = content.gameObject.AddComponent<VerticalLayoutGroup>();                            
                        }
                        break;
                }
                hov.childControlWidth = false;
                hov.childControlHeight = false;
                break;
            case enSFUI_ScrollRect_LayoutGroupType.GridLayoutGroup:
                GridLayoutGroup grid = _lg as GridLayoutGroup;
                if (!(_lg is GridLayoutGroup))
                {
                    _lg.ImmediateDestory();
                    grid = content.gameObject.AddComponent<GridLayoutGroup>();
                }
                switch (mScrollMode)
                {
                    case enSFUI_ScrollRect_ScrollMode.Horizontal:
                        grid.startAxis = GridLayoutGroup.Axis.Vertical;
                        grid.constraint = GridLayoutGroup.Constraint.Flexible;
                        break;
                    case enSFUI_ScrollRect_ScrollMode.Vertical:
                        grid.startAxis = GridLayoutGroup.Axis.Horizontal;
                        grid.constraint = GridLayoutGroup.Constraint.Flexible;
                        break;
                }
                break;
        }
    }
    #endregion

    #region OnInitSetting 初始化设定
    /// <summary>
    /// 初始化设定
    /// </summary>
    void OnInitSetting()
    {
        horizontal = mScrollMode == enSFUI_ScrollRect_ScrollMode.Horizontal && mCanScroll;
        vertical = mScrollMode == enSFUI_ScrollRect_ScrollMode.Vertical && mCanScroll;

        ContentSizeFitter.FitMode horizontalFit = horizontal ? ContentSizeFitter.FitMode.PreferredSize : ContentSizeFitter.FitMode.Unconstrained;
        ContentSizeFitter.FitMode verticalFit = vertical ? ContentSizeFitter.FitMode.PreferredSize : ContentSizeFitter.FitMode.Unconstrained;

        mLayoutGroup = content.gameObject.GetComponent<LayoutGroup>();
        OnCheckLayoutGroup(mLayoutGroup);

        ContentSizeFitter fitter = content.GetOrAddComponent<ContentSizeFitter>();
        fitter.horizontalFit = horizontalFit;
        fitter.verticalFit = verticalFit;

        //content.pivot = Vector2.up;
        switch (mScrollMode)
        {
            case enSFUI_ScrollRect_ScrollMode.Horizontal:
                content.anchorMin = Vector2.zero;
                content.anchorMax = Vector2.up;
                content.sizeDelta *= Vector2.right;
                break;
            case enSFUI_ScrollRect_ScrollMode.Vertical:
                content.anchorMin = Vector2.up;
                content.anchorMax = Vector2.one;
                content.sizeDelta *= Vector2.up;
                break;
        }
    }
    #endregion

    #region Awake
    /// <summary>
    /// Awake
    /// </summary>
    protected override void Awake()
    {
        base.Awake();
        if (Application.isPlaying)
        {
            OnInitSetting();
            OnInitItemRoot();
        }        
    }
    #endregion

    #region OnDestroy
    /// <summary>
    /// OnDestroy
    /// </summary>
    protected override void OnDestroy()
    {
        base.OnDestroy();
        if (mItemRootContainer != null)
        {
            Destroy(mItemRootContainer.gameObject);
        }
    }
    #endregion

    #region BindEvent 绑定事件
    /// <summary>
    /// 绑定事件
    /// </summary>
    /// <param name="_getItemCount">获得Item数量</param>
    /// <param name="_getItemTemplete">获得Item模板</param>
    /// <param name="_updateItem">更新Item</param>
    /// <param name="_funcBindSimulateBehaviour">绑定模拟脚本</param>
    public void BindEvent(Func<int> _getItemCount,Func<int, GameObject> _getItemTemplete, Action<SFUI_ScrollRectItem> _updateItem, Func<SFUI_ScrollRectItem, ISimulateBehaviour> _funcBindSimulateBehaviour)
    {
        mFuncGetItemCount = _getItemCount;
        mFuncGetItemTemplete = _getItemTemplete;
        mActionUpdateItem = _updateItem;
        mFuncBindSimulateBehaviour = _funcBindSimulateBehaviour;
    }
    #endregion

    #region SetInfiniteLoop 设置是否无限循环
    /// <summary>
    /// 设置是否无限循环
    /// </summary>
    /// <param name="_isInfiniteLoop">是否无限循环</param>
    public void SetInfiniteLoop(bool _isInfiniteLoop)
    {
        mIsInfiniteLoop = _isInfiniteLoop;
    }
    #endregion

#if UNITY_EDITOR
    #region EditorRefreshSetting 刷新设定
    /// <summary>
    /// 刷新设定
    /// </summary>
    public void EditorRefreshSetting()
    {
        if (!Application.isPlaying)
        {
            bool toHorizontal = mScrollMode == enSFUI_ScrollRect_ScrollMode.Horizontal;
            bool toVertical = mScrollMode == enSFUI_ScrollRect_ScrollMode.Vertical;
            if (
                horizontal != toHorizontal ||
                vertical != toVertical ||
                (horizontal == toHorizontal && mCanScroll != horizontal) ||
                (vertical == toVertical && mCanScroll != vertical))
            {
                OnInitSetting();
            }
        }            
    }
    #endregion
#endif
}